package com.conph.rpc.core;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.Socket;

public class RpcServerExecutor implements Runnable {
	private Socket socket;
	private DataInputStream dis;
	private DataOutputStream dos;
	private RpcServer rpcServer;
	private Gson gson;
	
	public RpcServerExecutor() {
		gson = new GsonBuilder().create();
	}
	
	RpcServerExecutor(RpcServer rpcServer, Socket socket, long threadId) throws Exception {
		this();
		this.socket = socket;
		this.rpcServer = rpcServer;
		this.dis = new DataInputStream(this.socket.getInputStream());
		this.dos = new DataOutputStream(this.socket.getOutputStream());
		new Thread(this, "RPC_EXECUTOR_" + threadId).start();
	}
	
	void closeSocket() {
		try {
			if (dis != null) {
				dis.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			dis = null;
		}
		try {
			if (dos != null) {
				dos.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			dos = null;
		}
		try {
			if (socket != null && !socket.isClosed()) {
				socket.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			socket = null;
		}
	}

	@Override
	public void run() {
		try {
		// 接收RPC客户端传递的rpcBeanId和参数；
			String rpcBeanId = dis.readUTF();
			String objArrJson = dis.readUTF();
			Object[] objArr = gson.fromJson(objArrJson, Object[].class);
		// 定位相关类、对象和方法；
			RpcBeanDefination defination;
			defination = rpcServer.getRpcBeanFactory().getRpcBean(rpcBeanId);
		// 执行RPC客户端要求执行的方法；
			Method method = defination.getMethod();
			Object object = defination.getObject();
			Class<?>[] paraTypes = method.getParameterTypes();
			for(int i = 0; i < objArr.length; i++) {
				if((paraTypes[i]).isInstance(objArr[i])) {
					objArr[i] = paraTypes[i].cast(objArr[i]);
				}else {
					System.out.println("2");
					objArr[i] = null;
				}
			}
			Object result = method.invoke(object, objArr);

		// 向RPC客户端返回执行结果。
			dos.writeUTF(gson.toJson(result));
		} catch (Throwable e) {
			e.printStackTrace();
		} finally {
			closeSocket();
		}
	}
	
}
